//=============================================================================
//                                                                            
//                               OpenMesh                                     
//      Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen       
//                           www.openmesh.org                                 
//                                                                            
//-----------------------------------------------------------------------------
//                                                                            
//                                License                                     
//                                                                            
//   This library is free software; you can redistribute it and/or modify it 
//   under the terms of the GNU Library General Public License as published  
//   by the Free Software Foundation, version 2.                             
//                                                                             
//   This library is distributed in the hope that it will be useful, but       
//   WITHOUT ANY WARRANTY; without even the implied warranty of                
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         
//   Library General Public License for more details.                          
//                                                                            
//   You should have received a copy of the GNU Library General Public         
//   License along with this library; if not, write to the Free Software       
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 
//                                                                            
//-----------------------------------------------------------------------------
//                                                                            
//   $Revision: 1.2 $
//   $Date: 2005-12-21 13:55:20 $
//                                                                            
//=============================================================================

/** \file CollapseInfoT.hh
Provides data class CollapseInfoT for storing all information
about a halfedge collapse.
*/

//=============================================================================
//
//  STRUCT CollpaseInfoT
//
//=============================================================================

#ifndef OPENMESH_DECIMATER_COLLAPSEINFOT_HH
#define OPENMESH_DECIMATER_COLLAPSEINFOT_HH


//== INCLUDES =================================================================

#include <vector>


//== NAMESPACE ================================================================

namespace OpenMesh  { 
	namespace Decimater {


		//== CLASS DEFINITION =========================================================

		/** Stores information about a halfedge collapse.

		The class stores information about a halfedge collapse. The most
		important information is \c v0v1, \c v1v0, \c v0, \c v1, \c vl,
		\c vr, which you can lookup in the following image:  
		\image html collapse_info.png
		\see ModProgMeshT::Info
		*/
		template <class Mesh>
		struct CollapseInfoT
		{
		public:
			/** Initializing constructor.
			*
			*  Given a mesh and a halfedge handle of the halfedge to be collapsed
			*  all important information of a halfedge collapse will be stored.
			* \param _mesh Mesh source 
			* \param _heh Halfedge to collapse. The direction of the halfedge
			*        defines the direction of the collapse, i.e. the from-vertex
			*        will be removed and the to-vertex remains.
			*/
			CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh);

			Mesh&                          mesh;

			typename Mesh::HalfedgeHandle  v0v1; ///< Halfedge to be collapsed
			typename Mesh::HalfedgeHandle  v1v0; ///< Reverse halfedge
			typename Mesh::VertexHandle    v0;   ///< Vertex to be removed
			typename Mesh::VertexHandle    v1;   ///< Remaining vertex
			typename Mesh::Point           p0;   ///< Position of removed vertex
			typename Mesh::Point           p1;   ///< Positions of remaining vertex
			typename Mesh::FaceHandle      fl;   ///< Left face
			typename Mesh::FaceHandle      fr;   ///< Right face
			typename Mesh::VertexHandle    vl;   ///< Left vertex
			typename Mesh::VertexHandle    vr;   ///< Right vertex
			//@{ 
			/** Outer remaining halfedge of diamond spanned by \c v0, \c v1, 
			*  \c vl, and \c vr
			*/
			typename Mesh::HalfedgeHandle  vlv1, v0vl, vrv0, v1vr;
			//@}
			/// The one-ring of vertex v0 (the one to be collapsed)
			std::vector<typename Mesh::VertexHandle>  one_ring;
		};


		//-----------------------------------------------------------------------------


		// CollapseInfoT::CollapseInfoT( _mesh, _heh )
		//
		//   Local configuration of halfedge collapse to be stored in CollapseInfoT:
		/* 
		vl
		* 
		/ \
		/   \
		/ fl  \
		v0 *------>* v1
		\ fr  /
		\   /
		\ /
		* 
		vr
		*/
		// Parameters:
		//   _mesh               Reference to mesh
		//   _heh                The halfedge (v0 -> v1) defining the collapse
		//
		template <class Mesh>
		inline
			CollapseInfoT<Mesh>::
			CollapseInfoT(Mesh& _mesh, typename Mesh::HalfedgeHandle _heh) :

		mesh(_mesh),
			v0v1(_heh),
			v1v0(_mesh.opposite_halfedge_handle(v0v1)),
			v0(_mesh.to_vertex_handle(v1v0)),
			v1(_mesh.to_vertex_handle(v0v1)),
			p0(_mesh.point(v0)),
			p1(_mesh.point(v1)),
			fl(_mesh.face_handle(v0v1)),
			fr(_mesh.face_handle(v1v0))

		{
			// get vl
			if (fl.is_valid())
			{
				vlv1 = mesh.next_halfedge_handle(v0v1);
				v0vl = mesh.next_halfedge_handle(vlv1);
				vl   = mesh.to_vertex_handle(vlv1);
				vlv1 = mesh.opposite_halfedge_handle(vlv1);
				v0vl = mesh.opposite_halfedge_handle(v0vl);
			}


			// get vr
			if (fr.is_valid())
			{
				vrv0 = mesh.next_halfedge_handle(v1v0);
				v1vr = mesh.next_halfedge_handle(vrv0);
				vr   = mesh.to_vertex_handle(vrv0);
				vrv0 = mesh.opposite_halfedge_handle(vrv0);
				v1vr = mesh.opposite_halfedge_handle(v1vr);
			}


			// store one-ring
			one_ring.clear();
			for (typename Mesh::VVIter vv_it=mesh.vv_iter(v0); vv_it; ++vv_it)
				one_ring.push_back(vv_it);
		}  

		//=============================================================================
	} // END_NS_DECIMATER
} // END_NS_OPENMESH
//=============================================================================
#endif // OPENMESH_DECIMATER_COLLAPSEINFOT_HH defined
//=============================================================================

